//microcommand define -lnn-pjsk-findcardcn
const { pathToFileURL } = require("url")
const { distance } = require("fastest-levenshtein")
inject(["puppeteer"])

const cache = Object.create(null);
const pendingPromises = Object.create(null);
const cacheDuration = 600_000;
async function getCached(url) {
  const now = Date.now();
  const cached = cache[url];

  if (cached && cached.expiry > now) {
    return cached.data;
  }

  if (pendingPromises[url]) {
    return pendingPromises[url];
  }

  try {
    pendingPromises[url] = (async () => {
      const headers = {};
      if (cached && cached.lastModified) {
        headers["If-Modified-Since"] = cached.lastModified;
      }

      const response = await ctx.http(url, {
        headers,
        validateStatus: status => status === 200 || status === 304,
      });

      if (response.status === 304) {
        cache[url].expiry = now + cacheDuration;
        return cached.data;
      }

      const lastModified = response.headers["last-modified"];
      cache[url] = {
        data: response.data,
        expiry: now + cacheDuration,
        lastModified,
      };
      return response.data;
    })();

    return await pendingPromises[url];
  } catch (error) {
    if (cached) {
      ctx.logger.warn(error);
      return cached.data;
    }
    throw error;
  } finally {
    delete pendingPromises[url];
  }
}

signature("<name:rawtext>")
action(async ({ session }, name) => {
  const cards = await getCached("https://sekai-world.github.io/sekai-master-db-cn-diff/cards.json")
  const characterNames = Object.fromEntries((await getCached("https://sekai-world.github.io/sekai-master-db-cn-diff/gameCharacters.json")).map(c => [c.id, (c.firstName || "") + c.givenName]))

  const distances = cards.map(c => distance(name, c.prefix + " " + characterNames[c.characterId]))
  const ind = distances.indexOf(Math.min(...distances))
  return h.text(cards[ind].prefix + " " + characterNames[cards[ind].characterId] + " https://sekai.best/card/" + cards[ind].id)
})